--[[-- 
     * 
     *  Copyright(c) 2017,  
     *  All rights reserved.
     *
     *  文件名称  : random.lua
     *  摘   要  :  获取随机数 
     * 
     *  当前本版  :  1.1   
     *  作   者  : 
     *  完成日期  :  
     *
     *  取代本版  : 
     *  原作者    :     
     *  完成日期  :
     *
--]]--

local random = {}

local N = 16
local MASK = (1 << N) - 1

local  	  X0 = 0X330E
local 	  X1 = 0XABCD
local	  X2 = 0X1234
local	  A0 = 0XE66D
local	  A1 = 0XDEEC
local	  A2 = 0X0005
local	  C  = 0X000B 

-- 获取低字节
local function LOW(x) 

	return (x & MASK) 	
end 

-- 获取高字节
local function HIGH(x)

	return LOW(x>>N)
end

-- 两者相加 是否 > 2^16 - 1
local function CARRY(x,y)

	if (x+y) > MASK then 
		return 1
	else
   		return 0	
	end 
end 

local function ADDEQU(x,y)

	return LOW(x+y)		
end 


local function MUL(x,y,z)

	local l = x*y
	z[1] = LOW(l)
	z[2] = HIGH(l)
end


local _x = {}
_x[1] = X0
_x[2] = X1
_x[3] = X2

local _a = {}
_a[1] = A0
_a[2] = A1
_a[3] = A2

local _c = C




local function _sh_next()
	
	local p = {}
	local q = {}
	local r = {}
	local c0
	local c1
	local l

	MUL(_a[1],_x[1],p)
	p[1] = ADDEQU(p[1],_c)
	c0 = CARRY(p[1],_c)
	
	p[2] =  ADDEQU(p[2], c0)
	c1 = CARRY(p[2],c0)

	MUL(_a[1],_x[2],q)
	p[1] = ADDEQU(p[2],q[1])
	c0 	 = CARRY(p[2],q[1])

	MUL(_a[2],_x[1],r)

	l = c0 + c1 + CARRY(p[2], r[1]) +q[2] +r[2] + _a[1]*_x[3] + _a[2] * _x[2] + _a[3] * _x[1];

	_x[3] = LOW(l)
	_x[2] = LOW(p[2] + r[1])
	_x[1] = LOW(p[1])
end 


-- 初始化随机种子  seed -> (uint32_t)time(NULL)
function random:sh_srand(seed)

	_x[1] = X0
	_x[2] = LOW(seed)
	_x[3] = HIGH(seed)

	_a[1] = A0
	_a[2] = A1
	_a[3] = A2
	_c = C	
end 

--sh_rand   -得到[0,INT32_MAX] 随机数  -> INT32_MAX = 2^31 = 7FFFFFFF
function random:sh_rand()
	
	_sh_next()
	return (_x[3] << (N-1)) + (_x[2] >> 1)
end 

--sh_rands  - 得到[min,max] 范围的随机数
function random:sh_rands(min, max)
		
	assert(min < max)
	return self:sh_rand() % ((max - min) + 1) + min
end 

return random -- 测试时记得去掉该行

--[[-- (去掉注释便可直接测试)

--测试用例
local old = os.clock()
random:sh_srand(os.time())		--使用前先初始化
print(random:sh_rand())			--得到[0,INT32_MAX] 随机数
print(random:sh_rands(1,20000))	--得到[min,max] 范围的随机数
print((os.clock() - old))

--]]--